package com.qf.leadnewsarticle.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.leadnewsarticle.mapper.ApArticleConfigMapper;
import com.qf.leadnewsarticle.mapper.ApArticleContentMapper;
import com.qf.leadnewsarticle.mapper.ArticleMapper;
import com.qf.leadnewsarticle.service.ArticleService;
import com.qf.qfleadnewscommons.minio.MinioOperator;
import com.qf.qfleadnewsfeignapi.wemedia.WeMediaApi;
import com.qf.qfleadnewsmodel.article.dtos.ArticleHomePageDto;
import com.qf.qfleadnewsmodel.article.pojos.ApArticle;
import com.qf.qfleadnewsmodel.article.pojos.ApArticleConfig;
import com.qf.qfleadnewsmodel.article.pojos.ApArticleContent;
import com.qf.qfleadnewsmodel.commons.dtos.ResponseResult;
import com.qf.qfleadnewsmodel.wemedia.pojos.WmNews;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, ApArticle> implements ArticleService {

    @Autowired
    private WeMediaApi weMediaApi;

    @Autowired
    private ApArticleConfigMapper apArticleConfigMapper;

    @Autowired
    private ApArticleContentMapper apArticleContentMapper;

    @Autowired
    private MinioOperator minioOperator;
    @Autowired
    private Configuration configuration;

    @Override
    public ResponseResult loadPage(ArticleHomePageDto articleHomePageDto) {

        List<ApArticle> apArticles = baseMapper.selectListByCondition(articleHomePageDto);

        return ResponseResult.okResult(apArticles);
    }

    @Override
    @Transactional
    public void publishNews(WmNews wmNews) {
        //保存ApArticle数据
        ApArticle apArticle = new ApArticle();
        BeanUtils.copyProperties(wmNews,apArticle);
        //设置作者id
        apArticle.setAuthorId(Long.valueOf(wmNews.getUserId()));
        //设置作者名称
        String username = weMediaApi.findUsernameById(wmNews.getUserId());
        apArticle.setAuthorName(username);
        //设置频道名称
        String channelname = weMediaApi.findChannelnameById(wmNews.getChannelId());
        apArticle.setChannelName(channelname);
        //设置封面布局
        apArticle.setLayout(wmNews.getType());
        //设置文章标记
        apArticle.setFlag((byte) 0);
        //设置同步状态
        apArticle.setSyncStatus(true);

        save(apArticle);

        //保存文章配置数据
        ApArticleConfig apArticleConfig = new ApArticleConfig(apArticle.getId());
        apArticleConfigMapper.insert(apArticleConfig);

        //保存文章内容数据
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());
        apArticleContent.setContent(wmNews.getContent());
        apArticleContentMapper.insert(apArticleContent);

        //通过远程调用修改Wemedia服务中wmnews的状态为9（已发布）
        weMediaApi.updateWmnewsStatusById(wmNews.getId(),apArticle.getId());

        //对文章内容实现静态化处理
        try {
            article2HTML(apArticleContent.getContent(),apArticle.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//    private void article2HTML(Long articleId) throws TemplateException, IOException {
    private void article2HTML(String content,Long articleId) throws TemplateException, IOException {
        //根据id查找内容
//        LambdaQueryWrapper<ApArticleContent> qw = Wrappers.lambdaQuery(ApArticleContent.class)
//                .eq(ApArticleContent::getArticleId, articleId);
//        ApArticleContent apArticleContent = apArticleContentMapper.selectOne(qw);
//
//        String content = apArticleContent.getContent();

        //将字符串类型的content转成数组/集合
        JSONArray jsonArray = JSONArray.parseArray(content);

        //数据模型
        Map map = new HashMap();
        map.put("content",jsonArray);

        Template template = configuration.getTemplate("article.ftl");

        /**
         * 这里我们将内容都直接在内存中处理，有一个风险。
         *      如果文章的内容过大，并发量很高，内存的开销就会剧增，最终结果可能会导致OOM问题
         *
         *      解决方案：基于临时文件操作
         *          StringWriter --> FileOutputStream
         *          ByteArrayInputStream --> FileInputStream
         *
         *  EasyExcel： 基于PIO做了进一步封装，解决了OOM问题
         *      PIO原始操作所有的数据操作都是在内存中完成的
         *      EasyExcel将内存操作换成本地临时文件操作
         */
        StringWriter os = new StringWriter();
        template.process(map,os);

        //将生成的html内容，上传到minio中
        InputStream is = new ByteArrayInputStream(os.toString().getBytes(StandardCharsets.UTF_8));
        String url = minioOperator.uploadHtml(is);

        //将url填充到article表中
        ApArticle article = new ApArticle();
        article.setId(articleId);
        article.setStaticUrl(url);
        updateById(article);
    }
}
